/**
 * 	 <GUI for Fourier Transform and Power spectrum>
 *   Copyright (C) <2011>  <Rishi Das Roy rishi.dasroy@gmail.com>

 * 	 This program is free software: you can redistribute it and/or modify
 * 	 it under the terms of the GNU General Public License as published by
 * 	 the Free Software Foundation, either version 3 of the License, or
 *	 (at your option) any later version.

 *	 This program is distributed in the hope that it will be useful,
 *	 but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	 GNU General Public License for more details.

 *	 You should have received a copy of the GNU General Public License
 *	 along with this program.  If not, see <http://www.gnu.org/licenses/>
 */
package testSwing;

import static testSwing.SignalFile.COMMA;
import static testSwing.SignalFile.SPACE;
import static testSwing.SignalFile.TAB;

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.border.Border;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.plaf.metal.DefaultMetalTheme;
import javax.swing.plaf.metal.MetalLookAndFeel;

import flanagan.math.FourierTransform;


/**
 * @author Rishi Das Roy
 *
 * @Organization Institute Of Genomics & Integrative Biology
 */
public class Dummy extends JFrame implements ActionListener, FocusListener, TreeSelectionListener{
	private static final String SAMPLE_SEC = "sample/sec";
	private JButton GraphButton;
	private JTextArea timeSeriesArea;
	private JTextField deltaT;
	private JScrollPane scroll;
	private JButton FourierButton;
	private JButton PowerLog;
	private JButton PowerSpectrum;
	private JRadioButton Rectangular;
	private JRadioButton Bartlett;
	private JRadioButton Welch;
	private JRadioButton Hann;
	private JRadioButton Hamming;
	private JRadioButton NoWindow;
	private double[] timeSeries;
	private JCheckBox overLap;
	private JRadioButton segNumber;
	private JRadioButton segLength;
	private JComboBox segCombo;
	private JTabbedPane seriesTabPane;
	private JTree fileTree;
	private SignalFile mSignalFile;
	private JCheckBox removeMean;
	private JButton Integral;
	private JButton Save2File;
	private final  JFileChooser fc = new JFileChooser();


	public Dummy() {
		this.setSize(600,650);
		this.setDefaultCloseOperation(
		JFrame.EXIT_ON_CLOSE);
		this.setTitle("Digital Signal Analysis");
		this.setLocationRelativeTo(null);
		validateEnvironment();

		JPanel mainPanel = new JPanel();
		mainPanel.setLayout(new GridBagLayout());

		JLabel l1 = new JLabel();
		l1.setText("GUI for Fourier Transform \n using Dr Michael Thomas Flanagan's Library");
		addItem(mainPanel, l1, 0, 0, 3, 1, GridBagConstraints.NORTH);

		timeSeriesUI(mainPanel);



		JPanel BasicPanel = basicUI();
		addItem(mainPanel, BasicPanel, 1, 1, 2, 1, GridBagConstraints.NORTH);

		JPanel psPanel = new JPanel(new GridBagLayout());
		Border psBorder =  BorderFactory.createTitledBorder("Power Spectral Analysis");
		psPanel.setBorder(psBorder);
		addPSoptios(psPanel);

		addItem(mainPanel, psPanel, 1, 2, 2, 1, GridBagConstraints.NORTH);

		this.add(mainPanel);
		this.setVisible(true);
	}

	private JPanel basicUI() {
		JPanel BasicPanel = new JPanel(new GridBagLayout());
		Border B2 = BorderFactory.createTitledBorder("Basic");
		BasicPanel.setBorder(B2);
		JLabel deltaLabel = new JLabel();
		deltaLabel.setText(SAMPLE_SEC);
		addItem(BasicPanel, deltaLabel, 0, 0, 1, 1, GridBagConstraints.CENTER);
		deltaT = new DoubleTextField(10);
		addItem(BasicPanel, deltaT, 1, 0, 1, 1, GridBagConstraints.CENTER);
		GraphButton = new JButton();
		GraphButton.setText("Plot Graph");
		GraphButton.addActionListener(this);
		addItem(BasicPanel, GraphButton, 0, 1, 1, 1, GridBagConstraints.CENTER);
		FourierButton = new JButton();
		FourierButton.setText("Fourier Transform");
		FourierButton.addActionListener(this);
		addItem(BasicPanel, FourierButton, 1, 1, 1, 1, GridBagConstraints.CENTER);
		return BasicPanel;
	}

	private void timeSeriesUI(JPanel mainPanel) {
		Border timeBorder = BorderFactory.createTitledBorder("Time series here!!");
		seriesTabPane = new JTabbedPane();
		seriesTabPane.setPreferredSize(new Dimension(200,475));
		seriesTabPane.setBorder(timeBorder);

		JPanel timePanel = new JPanel(false);
		timePanel.setLayout(new GridLayout(1,1));
		timePanel.setPreferredSize(new Dimension(200,400));
		timeSeriesArea = new JTextArea(27,15);
		scroll = new JScrollPane(timeSeriesArea,
				JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
				JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
				timePanel.add(scroll);
				//timeSeriesArea.addFocusListener(this);




		JPanel timePanel1 = new JPanel(false);
		timePanel1.setLayout(new GridLayout(1,1));
		timePanel1.setPreferredSize(new Dimension(200,450));
		//JTextArea timeSeriesArea1 = new JTextArea(27,15);
		FileSystemModel fileSystemModel = new FileSystemModel(new File(System.getProperty("user.home")));
//		FileSystemModel fileSystemModel = new FileSystemModel(new File("/home/rishi.das/tmp/R5_files_For_Rishi"));
	    fileTree = new JTree(fileSystemModel);

	    fileTree.setEditable(true);
	    fileTree.addTreeSelectionListener(this);
	    /*new TreeSelectionListener() {



		    }*/
		JScrollPane scroll1 = new JScrollPane(fileTree,
				JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
				JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
				timePanel1.add(scroll1);

		seriesTabPane.addTab("File", timePanel1);
		seriesTabPane.setMnemonicAt(0, KeyEvent.VK_1);
		seriesTabPane.addTab("User", timePanel);

		seriesTabPane.setMnemonicAt(0, KeyEvent.VK_2);
	    addItem(mainPanel, seriesTabPane, 0, 1, 1, 8, GridBagConstraints.NORTH);
	}

	private void validateEnvironment() {
		String version = System.getProperty("java.version");
	    char minor = version.charAt(2);
	    if(minor < '6' ){
	    	JOptionPane.showMessageDialog(
					this,
					"You need Java 6 to run DSA \n You are presently using "+version,
					"Update Java",JOptionPane.ERROR_MESSAGE);
	    	System.exit(0);
	    }


	}

	private void addPSoptios(JPanel psPanel) {
		JPanel windowPanel = new JPanel(new GridBagLayout());
		Border windowBorder =  BorderFactory.createTitledBorder("Window");
		windowPanel.setBorder(windowBorder);
		addItem(psPanel, windowPanel, 0, 0, 1, 1, GridBagConstraints.NORTH);
		Rectangular = new JRadioButton("Rectangular"); Bartlett = new JRadioButton("Bartlett") ;
		Welch = new JRadioButton("Welch"); Hann = new JRadioButton("Hann");
		Hamming = new JRadioButton("Hamming"); NoWindow = new JRadioButton("No Window");
		NoWindow.setSelected(true);



		ButtonGroup windowGroup = new ButtonGroup();
		windowGroup.add(Rectangular);
		windowGroup.add(Bartlett);
		windowGroup.add(Welch);
		windowGroup.add(Hann);
		windowGroup.add(Hamming);
		windowGroup.add(NoWindow);

		//JLabel RectangularLabel = new JLabel();
		addItem(windowPanel, Rectangular, 0, 0, 1, 1, GridBagConstraints.WEST);
		addItem(windowPanel, Bartlett, 1, 0, 1, 1, GridBagConstraints.WEST);
		addItem(windowPanel, Welch, 0, 1, 1, 1, GridBagConstraints.WEST);
		addItem(windowPanel, Hann, 1, 1, 1, 1, GridBagConstraints.WEST);
		addItem(windowPanel, Hamming, 0, 2, 1, 1, GridBagConstraints.WEST);
		addItem(windowPanel, NoWindow, 1, 2, 1, 1, GridBagConstraints.WEST);


		JPanel segmentPanel = new JPanel(new GridBagLayout());
		Border segmentBorder =  BorderFactory.createTitledBorder("Segment");
		segmentPanel.setBorder(segmentBorder);
		addItem(psPanel, segmentPanel, 0, 1, 2, 1, GridBagConstraints.NORTH);

		overLap = new JCheckBox("Overlap");
		overLap.addActionListener(this);
		addItem(segmentPanel, overLap, 0, 0, 1, 1, GridBagConstraints.WEST);
		removeMean = new JCheckBox("Remove Mean");
		addItem(segmentPanel, removeMean, 1, 0, 1, 1, GridBagConstraints.WEST);


		segLength = new JRadioButton("Length");
		segNumber = new JRadioButton("Number");
		segLength.addActionListener(this);
		segNumber.addActionListener(this);
		ButtonGroup segGroup = new ButtonGroup();
		segGroup.add(segLength);
		segGroup.add(segNumber);

		addItem(segmentPanel, segLength, 0, 1, 1, 1, GridBagConstraints.WEST);
		addItem(segmentPanel, segNumber, 1, 1, 1, 1, GridBagConstraints.WEST);

		JLabel segLabel = new JLabel("Lenght/Number");
		segCombo = new JComboBox();
		addItem(segmentPanel, segLabel, 0, 2, 1, 1, GridBagConstraints.WEST);
		addItem(segmentPanel, segCombo, 1, 2, 1, 1, GridBagConstraints.WEST);

		PowerSpectrum = new JButton("Power Spectrum");
		PowerSpectrum.addActionListener(this);
		PowerLog = new JButton("Log Power Spectrum");
		PowerLog.addActionListener(this);
		addItem(segmentPanel, PowerSpectrum, 0, 3, 1, 1, GridBagConstraints.WEST);
		addItem(segmentPanel, PowerLog, 1, 3, 1, 1, GridBagConstraints.WEST);

		Integral = new JButton("Integral Area");
		Integral.addActionListener(this);
		addItem(segmentPanel, Integral, 0, 4, 1, 1, GridBagConstraints.WEST);

		Save2File = new JButton("Extract time series");
		Save2File.setToolTipText("Useful to extract a particular column from a csv file");
		Save2File.addActionListener(this);
		addItem(segmentPanel, Save2File, 1, 4, 1, 1, GridBagConstraints.WEST);


	}

	public static void main(String[] args) {
		 try {
			    // Set cross-platform Java L&F (also called "Metal")
			 try {
				    for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
				        if ("Nimbus".equals(info.getName())) {
				            UIManager.setLookAndFeel(info.getClassName());
				            break;
				        }
				    }
				} catch (Exception e) {
					MetalLookAndFeel.setCurrentTheme(new DefaultMetalTheme());
					 //UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
					 UIManager.setLookAndFeel(new MetalLookAndFeel());
				}


		    }
		    catch (UnsupportedLookAndFeelException e) {
		       // handle exception
		    } /*catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block

			} catch (InstantiationException e) {
				// TODO Auto-generated catch block

			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block

			}*/


		new Dummy();
	}

	public void actionPerformed(ActionEvent e) {
		if(e.getSource() == segLength || e.getSource() == segNumber || e.getSource() == overLap){
			updateSegment();
			return;
		}

		PlotThread lGraphThread = null;
		if (e.getSource() == GraphButton && isBasicValid()) {
			lGraphThread = new PlotThread(timeSeries, Double.parseDouble(deltaT
					.getText()), PlotThread.GRAPH);
		} else if (e.getSource() == FourierButton && isBasicValid()) {
			lGraphThread = new PlotThread(timeSeries, Double.parseDouble(deltaT
					.getText()), PlotThread.FOURIER);
		} else if(e.getSource() == PowerSpectrum && isAdvncValid()){
			lGraphThread = new PlotThread(timeSeries, Double.parseDouble(deltaT
					.getText()), PlotThread.POWER_SPECTRUM);
			advncGraph(lGraphThread);
		} else if(e.getSource() == PowerLog && isAdvncValid()){
			lGraphThread = new PlotThread(timeSeries, Double.parseDouble(deltaT
					.getText()), PlotThread.POWER_LOG);
			advncGraph(lGraphThread);
		}else if(e.getSource() == Integral && isAdvncValid()){
			lGraphThread = new PlotThread(timeSeries, Double.parseDouble(deltaT
					.getText()), PlotThread.INTEGRAL);
			advncGraph(lGraphThread);
		}else if(e.getSource() == Save2File && isBasicValid()){
			saveToFile();
		}


		if(lGraphThread!=null){
			lGraphThread.start();
		}

	}

	private void saveToFile() {
		int returnVal = fc.showSaveDialog(this);
		//fc.setApproveButtonText();
		//fc.setOpaque(true);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            try {
				BufferedWriter brWr = new BufferedWriter(new FileWriter(file));
				for (double element : timeSeries) {
					brWr.write(element+System.getProperty("line.separator"));
				}
				brWr.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				//log.error(e);
			}
        } else {
          //  log.append("Open command cancelled by user." + newline);
        }


	}

	private void updateSegment() {
		if(isBasicValid()){
			if(segLength.isSelected()){
				int lengthFactor = overLap.isSelected() ? 2 :1;
				int numOfPoints= lengthFactor*FourierTransform.nextPowerOfTwo(timeSeries.length);
				segCombo.removeAllItems();
				for (int i = 2; i < numOfPoints; i=i*2) {
					segCombo.addItem(i);
				}
			}else if(segNumber.isSelected()){
				int numberFactor = overLap.isSelected() ? 1 :0;
				int numOfPoints= FourierTransform.nextPowerOfTwo(timeSeries.length);
				segCombo.removeAllItems();
				for (int i = 2; i < numOfPoints; i=i*2) {
					segCombo.addItem(i-numberFactor);
				}
			}
		}

	}

	private boolean isAdvncValid() {
		// TODO Implement advance validation
		return isBasicValid();
	}

	private void advncGraph(PlotThread graphThread) {
		if(Rectangular.isSelected()){
			graphThread.getFourier().setRectangular();
		}else if(Bartlett.isSelected()){
			graphThread.getFourier().setBartlett();
		}else if(Welch.isSelected()){
			graphThread.getFourier().setWelch();
		}else if(Hann.isSelected()){
			graphThread.getFourier().setHann();
		}else if(Hamming.isSelected()){
			graphThread.getFourier().setHamming();
		}else {
			graphThread.getFourier().removeWindow();
		}

		if(overLap.isSelected()){
			graphThread.getFourier().setOverlapOption(true);
		}else {
			graphThread.getFourier().setOverlapOption(false);
		}

		if(removeMean.isSelected()){
			graphThread.setRemoveMean(true);
		}else{
			graphThread.setRemoveMean(false);
		}

		if(segLength.isSelected()){
			graphThread.getFourier().setSegmentLength((Integer)(segCombo.getSelectedItem()));
		}else if(segNumber.isSelected()){
			graphThread.getFourier().setSegmentNumber((Integer)(segCombo.getSelectedItem()));
		}

	}

	private boolean isBasicValid() {
		StringBuilder sb = new StringBuilder("");
		validateTimeSeries(sb);
		try {
			Double.parseDouble(deltaT
						.getText());
		} catch (NumberFormatException e) {
			sb.append("Enter real number for "+SAMPLE_SEC+"\n");
		}
		if(sb.length()>0){
			JOptionPane.showMessageDialog(
					deltaT,
					sb.toString(),
					"Input Error",
					JOptionPane.ERROR_MESSAGE);

			return false;
		}
		return true;
	}

	private void validateTimeSeries(StringBuilder sb) {
		if(seriesTabPane.getSelectedIndex()==1){
			String[] series = timeSeriesArea.getText().split("\n");
			timeSeries = new double[series.length];
			try {
				for (int i = 0; i < series.length; i++) {
					timeSeries[i] = Double.parseDouble(series[i]);
				}
			} catch (NumberFormatException e) {
				sb.append("Enter real numbers for Time Series \n");
			}
		}else {
			if(mSignalFile == null){
				sb.append("No File is choosen.\n");
			} else {
				try {
					timeSeries = mSignalFile.getTimeSeries();
					if(timeSeries == null){
						sb.append("Some error in the file.");
					}
				} catch (Exception e) {
					sb.append("Some error in the file --."+ e.getMessage());

				}
			}
		}
	}

	/**
	 * Copied from "Java™ A L L - I N - O N E D E S K R E F E R E N C E FOR DUMmIES"
	 * @param p
	 * @param c
	 * @param x
	 * @param y
	 * @param width
	 * @param height
	 * @param align
	 */
	private void addItem(JPanel p, JComponent c, int x, int y,
			int width, int height, int align)
			{
			GridBagConstraints gc = new GridBagConstraints();
			gc.gridx = x;
			gc.gridy = y;
			gc.gridwidth = width;
			gc.gridheight = height;
			gc.weightx = 100.0;
			gc.weighty = 100.0;
			gc.insets = new Insets(5, 5, 5, 5);
			gc.anchor = align;
			gc.fill = GridBagConstraints.NONE;
			p.add(c, gc);
			}

	public void focusGained(FocusEvent pFE) {
		System.out.println("focusGained");

	}

	public void focusLost(FocusEvent pFE) {
		System.out.println("focusLost");

	}

	public void valueChanged(TreeSelectionEvent arg0) {
        File userSlctdFile = (File) fileTree.getLastSelectedPathComponent();
        if(userSlctdFile!=null  && isReadable(userSlctdFile)){
        	 mSignalFile = new SignalFile(userSlctdFile);
        	 configCsvFile();
        	 if(userSlctdFile.getName().endsWith("csv") || userSlctdFile.getName().endsWith("txt")){
        		 configCsvFile();
        	 }/*else if(userSlctdFile.getName().endsWith("erg")){
        		 configERGFile();
        	 }*/

    	}
	}

	private void configERGFile() {
		mSignalFile.setERG(true);
		String[] ergHeader = null;
		try {
			ergHeader = mSignalFile.getERGHeader();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println(e);
		}
		JPanel BasicPanel = new JPanel(new GridBagLayout());
		JLabel startLabel = new JLabel();
		startLabel.setText("Select the series");
		addItem(BasicPanel, startLabel, 0, 0, 1, 1, GridBagConstraints.CENTER);
		JComboBox headerCombo = new JComboBox();
		for (String string : ergHeader) {
			headerCombo.addItem(string);
		}

		addItem(BasicPanel, headerCombo, 0, 1, 1, 1, GridBagConstraints.CENTER);
		JOptionPane optionPane = new JOptionPane();
		optionPane.setMessage(BasicPanel);
		optionPane.setMessageType(JOptionPane.INFORMATION_MESSAGE);
		JDialog dialog = optionPane.createDialog(null, mSignalFile.getFileName());
		dialog.setVisible(true);
		mSignalFile.setColNum(headerCombo.getSelectedIndex()+1);
		mSignalFile.setColSep(TAB);
		mSignalFile.setStartLine(13);

	}

	private void configCsvFile() {
		JPanel BasicPanel = new JPanel(new GridBagLayout());
		JLabel startLabel = new JLabel();
		startLabel.setText("Data starts on line");
		addItem(BasicPanel, startLabel, 0, 0, 1, 1, GridBagConstraints.CENTER);
		JTextField startOfData = new IntegerTextField(10);

		startOfData.setText("1");
		addItem(BasicPanel, startOfData, 1, 0, 1, 1, GridBagConstraints.CENTER);

		JLabel endLabel = new JLabel();
		endLabel.setText("Data ends on line");
		addItem(BasicPanel, endLabel, 0, 1, 1, 1, GridBagConstraints.CENTER);

		JRadioButton endOfFile = new JRadioButton("End of the file.");
		endOfFile.setSelected(true);
		JRadioButton numtEndOfLine = new JRadioButton("Line:");
		ButtonGroup segGroup = new ButtonGroup();
		segGroup.add(endOfFile);
		segGroup.add(numtEndOfLine);

		addItem(BasicPanel, endOfFile, 1, 1, 1, 1, GridBagConstraints.WEST);
		addItem(BasicPanel, numtEndOfLine, 1, 2, 1, 1, GridBagConstraints.WEST);
		JTextField endOfData = new IntegerTextField(10);
//    		endOfData.setEditable(false);
		addItem(BasicPanel, endOfData, 2, 2, 1, 1, GridBagConstraints.CENTER);

		JLabel columnDel = new JLabel();
		columnDel.setText("Column delimiter:");
		JComboBox delCombo = new JComboBox();
		delCombo.addItem(COMMA);delCombo.addItem(TAB);delCombo.addItem(SPACE);
		JLabel columnNumber = new JLabel();
		columnNumber.setText("Column Number:");
		JTextField columnText = new IntegerTextField(10);
		addItem(BasicPanel, columnDel, 0, 3, 1, 1, GridBagConstraints.CENTER);
		addItem(BasicPanel, delCombo, 1, 3, 1, 1, GridBagConstraints.CENTER);
		addItem(BasicPanel, columnNumber, 0, 4, 1, 1, GridBagConstraints.CENTER);
		addItem(BasicPanel, columnText, 1, 4, 1, 1, GridBagConstraints.CENTER);


		JOptionPane optionPane = new JOptionPane();
		optionPane.setMessage(BasicPanel);
		optionPane.setMessageType(JOptionPane.INFORMATION_MESSAGE);
		JDialog dialog = optionPane.createDialog(null, "Width 100");
		boolean fileConfigdone = false;
		while(!fileConfigdone){
			dialog.setVisible(true);
//    	    	mSignalFile.

			try {
				mSignalFile.setStartLine(Integer.parseInt(startOfData.getText()));
				if(!endOfFile.isSelected())
					mSignalFile.setEndLine(Integer.parseInt(endOfData.getText()));

				mSignalFile.setColSep((String)delCombo.getSelectedItem());
				mSignalFile.setColNum(Integer.parseInt(columnText.getText()));
				fileConfigdone = true;
			} catch (NumberFormatException e) {
				 JOptionPane.showMessageDialog(
			        		this,
							"Please enter the text as Integer",
							"Error",JOptionPane.ERROR_MESSAGE);
			        }
			}
	}

	private boolean isReadable(File file) {
		// TODO Auto-generated method stub
		return ( file.isFile() && ( file.getName().endsWith("csv") || file.getName().endsWith("erg")));
	}



}

